package org.duang.tags;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;

import org.duang.config.Config;
import org.duang.kit.ToolsKit;

@SuppressWarnings("serial")
public class MAC2 extends BodyTagSupport {

	private String name;
	private String sRemoteAddr;
	private int iRemotePort = 137;
	private byte[] buffer = new byte[1024];
	private DatagramSocket ds = null;

	/**
	 * 是否执行自定义标签的标签体,是否创建一个缓冲区对象捕获标签体的执行结果,从而让标签开发者在标签处理种对标签体的执行结果进行修改,
	 * 其返回值可以是一下三个: EVAL_BODY_INCLUDE(执行标签体), SKIP_BODY(跳过标签体),
	 * EVAL_BODY_BUFFERED(把标签体放到缓冲区中,以便进一步处理)
	 */
	@Override
	public int doStartTag() throws JspException {
		try {
			name = (ToolsKit.isEmpty(name)) ? Config.getProductCode() + "_MAC" : name;
			pageContext.getOut().write(buildGetMACHtml());
			// pageContext.getOut().write(url);
		} catch (Exception e) {
			e.printStackTrace();
		}
		// return EVAL_BODY_INCLUDE; //执行doAfterBody()方法
		// return EVAL_BODY_BUFFERED;
		return SKIP_BODY;
	}

	/**
	 * EVAL_BODY_AGAIN(表示再执行标签体一次), SKIP_BODY(表示结束标签体执行继续执行doEndTag)
	 */
	@Override
	public int doAfterBody() throws JspException {
		return SKIP_BODY; // 表示结束标签体执行继续执行doEndTag
	}

	/**
	 * 控制是否执行结束标签后面的内容, 其返回值可以为: EVAL_PAGE(表示继续执行结束标签后面的jsp代码);
	 * SKIP_PAGE(表示忽略结束标签后面的jsp代码).
	 */
	@SuppressWarnings("static-access")
	@Override
	public int doEndTag() throws JspException {
		return this.EVAL_PAGE;
	}

	// 构建HTML
	public String buildGetMACHtml() {
		// StringBuilder macStr = new StringBuilder();
		// macStr.append("<%@page import=\"java.net.InetAddress\" %>");
		// macStr.append("<%@page import=\"java.net.NetworkInterface\" %>");
		// macStr.append("<% StringBuilder macSb = new StringBuilder();");
		// macStr.append("try{")
		// .append("InetAddress ip = InetAddress.getLocalHost();")
		// .append("NetworkInterface network =
		// NetworkInterface.getByInetAddress(ip);")
		// .append("byte[] mac = network.getHardwareAddress();")
		// .append("for (int i = 0; i < mac.length; i++) {")
		// .append("macSb.append(String.format(\"%02X%s\", mac[i], (i <
		// mac.length - 1) ? \"-\" : \"\"));")
		// .append("}")
		// .append("} catch(Exception e){")
		// .append("e.printStackTrace();")
		// .append("} %>");
		StringBuilder macStr = new StringBuilder();

//		Process process = Runtime.getRuntime().exec("nbtstat -a " + sip);
//		InputStreamReader ir = new InputStreamReader(process.getInputStream());

//		StringBuilder sb = new StringBuilder();
//		try {
//			InetAddress ip = InetAddress.getLocalHost();
//			NetworkInterface network = NetworkInterface.getByInetAddress(ip);
//			byte[] mac = network.getHardwareAddress();
//
//			for (int i = 0; i < mac.length; i++) {
//				sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""));
//			}
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
		
		HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
		String smac = "";
		String sip = request.getHeader("x-forwarded-for");   
		if(sip == null || sip.length() == 0 || "unknown".equalsIgnoreCase(sip)) {   
		    sip = request.getHeader("Proxy-Client-IP");   
		}   
		if(sip == null || sip.length() == 0 || "unknown".equalsIgnoreCase(sip)) {   
		    sip = request.getHeader("WL-Proxy-Client-IP");   
		}   
		if(sip == null || sip.length() == 0 || "unknown".equalsIgnoreCase(sip)) {   
		    sip = request.getRemoteAddr();   
		}   
		System.out.println("@@@@@@@@@@@sip: " + sip);
		try {
			UdpGetClientMacAddr(sip);
			smac = GetRemoteMacAddr();
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("@@@@@@@@@@@smac: " + smac);
		macStr.append("<input type='hidden' id='_duangMac").append(name).append("_").append("' name='").append(name)
				.append("' value='").append(smac).append("'/>");

		return macStr.toString();
	}
	
	private void UdpGetClientMacAddr(String strAddr) throws SocketException {
		sRemoteAddr = strAddr;
        ds = new DatagramSocket();
	}

	protected final DatagramPacket send(final byte[] bytes) throws IOException {
		DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName(sRemoteAddr), iRemotePort);
		ds.send(dp);
		return dp;
	}

	protected final DatagramPacket receive() throws Exception {
		DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
		ds.receive(dp);
		return dp;
	}

	protected byte[] GetQueryCmd() throws Exception {
		byte[] t_ns = new byte[50];
		t_ns[0] = 0x00;
		t_ns[1] = 0x00;
		t_ns[2] = 0x00;
		t_ns[3] = 0x10;
		t_ns[4] = 0x00;
		t_ns[5] = 0x01;
		t_ns[6] = 0x00;
		t_ns[7] = 0x00;
		t_ns[8] = 0x00;
		t_ns[9] = 0x00;
		t_ns[10] = 0x00;
		t_ns[11] = 0x00;
		t_ns[12] = 0x20;
		t_ns[13] = 0x43;
		t_ns[14] = 0x4B;

		for (int i = 15; i < 45; i++) {
			t_ns[i] = 0x41;
		}

		t_ns[45] = 0x00;
		t_ns[46] = 0x00;
		t_ns[47] = 0x21;
		t_ns[48] = 0x00;
		t_ns[49] = 0x01;
		return t_ns;
	}

	protected final String GetMacAddr(byte[] brevdata) throws Exception {

		int i = brevdata[56] * 18 + 56;
		String sAddr = "";
		StringBuffer sb = new StringBuffer(17);

		for (int j = 1; j < 7; j++) {
			sAddr = Integer.toHexString(0xFF & brevdata[i + j]);
			if (sAddr.length() < 2) {
				sb.append(0);
			}
			sb.append(sAddr.toUpperCase());
			if (j < 6)
				sb.append(':');
		}
		return sb.toString();
	}

	public final void close() {
		try {
			ds.close();
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	public final String GetRemoteMacAddr() throws Exception {
		byte[] bqcmd = GetQueryCmd();
		send(bqcmd);
		DatagramPacket dp = receive();
		String smac = GetMacAddr(dp.getData());
		close();
		return smac;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}
